﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
using System.Web.Services.Protocols;
using System.Xml;
using YunLib.Common;

namespace Yunlib.Common
{
    public class Reflect<T> where T : class,new()
    {
        private static Hashtable objCache = new Hashtable();
        private static object syncRoot = new Object();

        /// <summary>
        /// 唯一实例
        /// </summary>
        public static T Instance
        {
            get
            {
                //PerformanceTest pt = new PerformanceTest();
                //pt.Start();
                string CacheKey = typeof(T).FullName;
                T bll = (T)objCache[CacheKey];　 //从缓存读取      
                if (bll == null)
                {
                    lock (syncRoot)
                    {
                        if (bll == null)
                        {
                            bll = System.Activator.CreateInstance<T>(); //创建实例，并缓存    

                            if (typeof(T).IsSubclassOf(typeof(SoapHttpClientProtocol)))
                            {
                                ResetWebUrl(bll as SoapHttpClientProtocol);
                            }
                            objCache.Add(typeof(T).FullName, bll);

                            //Debug.WriteLine("类名:{0}".FormatWith(typeof(T).FullName));
                        }
                    }
                }

                if (bll is SoapHttpClientProtocol)
                {
                    var _instance = bll as SoapHttpClientProtocol;
                    //if (!_instance.Url.StartsWith(ConfigManager.CurrentLoginServerUrl))
                    //    ResetWebUrl(_instance);
                }
                //pt.End();
                return bll;
            }
        }

        /// <summary>
        /// webservice地址
        /// </summary>
        static string WebURL
        {
            get
            {
                string LocalService = ConfigManager.BooksManager;

                if (LocalService == null || LocalService.Length == 0 || LocalService.Trim().Length == 0)
                    throw new Exception("未配置服务接口地址.");
                else
                {
                    LocalService = LocalService.Trim();

                    if (!LocalService.EndsWith("/"))
                        LocalService = LocalService + "/";

                    return LocalService;
                }
            }
        }

        /// <summary>
        /// 重设webservice的url
        /// </summary>
        /// <param name="instance"></param>
        //[DebuggerStepThrough]
        static void ResetWebUrl(SoapHttpClientProtocol service)
        {
            string turl = service.Url;

            if (WebURL != "")
            {
                Regex regex = new Regex(@"http://([a-zA-Z0-9.:]+)/", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Multiline | RegexOptions.Singleline);

                turl = regex.Replace(turl, WebURL);
                service.Url = turl;
                AddCookie(ref service);
           
                System.Diagnostics.Debug.WriteLine(turl);
            }

            service.Timeout = 300000;//5分钟
        }


        static void AddCookie(ref SoapHttpClientProtocol service)
        {
            CookieContainer cookies = new System.Net.CookieContainer();

            string cookieDomain = new Uri(service.Url).Host;

            foreach (string cookieKey in HttpContext.Current.Request.Cookies.AllKeys)
            {
                System.Net.Cookie netCookie = new System.Net.Cookie(cookieKey, HttpContext.Current.Request.Cookies[cookieKey].Value, "/", cookieDomain);

                netCookie.Expires = DateTime.Now.AddMinutes(5);

                cookies.Add(netCookie);
            }

            service.CookieContainer = cookies;
        }

        public static R Invoke<R>(Func<T, R> methodFunc)
           where R : new()
        {
            return methodFunc(Reflect<T>.Instance);
        }

        public static void Invoke(Action<T> method)
        {
            method(Reflect<T>.Instance);
        }

        /// <summary>
        /// webservice使用方法
        /// </summary>
        /// <typeparam name="K">调用webservice后反序列化后的结果类型</typeparam>
        /// <param name="method">要调用的webservice的方法</param>
        /// <param name="action">对结果处理方法</param>
        public static void Run(Func<T, XmlNode> method, Action<RetuenData> action = null)
        {
            RetuenData returnObject = Reflect<T>.GetReturnObject(method(Reflect<T>.Instance));

            if (action != null)
                action(returnObject);
        }

        /// <summary>
        /// webservice使用方法
        /// </summary>
        /// <typeparam name="K">ReturnObject</typeparam>
        /// <typeparam name="S">最终的结果数据类型</typeparam>
        /// <param name="methodFunc">要调用的webservice的方法</param>
        /// <param name="resultFunc">对结果处理方法</param>
        /// <returns>返回最终的结果</returns>
        public static R Run<R>(Func<T, XmlNode> methodFunc, Func<RetuenData, R> func)
            where R : new()
        {

            RetuenData returnObject = Reflect<T>.GetReturnObject(methodFunc(Reflect<T>.Instance));

            return func(returnObject);
        }

        /// <summary>
        /// 获取一个ReturnObject对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xNode"></param>
        /// <returns></returns>
        public static RetuenData GetReturnObject(XmlNode xNode)
        {
            if (xNode == null) return null;

            return MethodHelper.DeserializeForReturnObject<RetuenData>(xNode);
        }
    }
}
